package com.dkm.biz.gl.util.word;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.dkm.base.api.constants.RedisConstants;
import com.dkm.base.core.helper.SpringHelper;
import com.dkm.biz.gl.service.GlFilterVocabularyService;

/**
 * 描述：敏感词过滤工具
 * 构建组：biz-bbs
 * 作者：徐浩文
 * 邮箱: xuhaowen@skg.com
 * 日期:Jul 8, 2015-4:46:52 PM
 * 版权：SKG 公司版权所有
 * </pre>
 * 
 * 于2015-10-12 归类并移动至biz-gl下  zhongjinyou
 */
public class WordFilterUtil {

	public  static Node tree=null;
	static GlFilterVocabularyService glFilterVocabularyService =SpringHelper.getBean(GlFilterVocabularyService.class);

	static {
		if(tree==null){
			glFilterVocabularyService.addGlFilterVocabulary();
		}
	}

	public static void insertWord(Node tree,String word, int level) {
		Node node = tree;
		for (int i = 0; i < word.length(); i++) {
			node = node.addChar(word.charAt(i));
		}
		node.setEnd(true);
		node.setLevel(level);
	}
	
	/*public static void insertWord(String word, int level) {
		Node node = tree;
		for (int i = 0; i < word.length(); i++) {
			node = node.addChar(word.charAt(i));
		}
		node.setEnd(true);
		node.setLevel(level);
	}*/

	private static boolean isPunctuationChar(String c) {
		String regex = "[\\pP\\pZ\\pS\\pM\\pC]";
		Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(c);
		return m.find();
	}

	private static PunctuationOrHtmlFilteredResult filterPunctation(String originalString) {
		StringBuffer filteredString = new StringBuffer();
		ArrayList<Integer> charOffsets = new ArrayList<Integer>();
		for (int i = 0; i < originalString.length(); i++) {
			String c = String.valueOf(originalString.charAt(i));
			if (!isPunctuationChar(c)) {
				filteredString.append(c);
				charOffsets.add(i);
			}
		}
		PunctuationOrHtmlFilteredResult result = new PunctuationOrHtmlFilteredResult();
		result.setOriginalString(originalString);
		result.setFilteredString(filteredString);
		result.setCharOffsets(charOffsets);
		return result;
	}

	private static PunctuationOrHtmlFilteredResult filterPunctationAndHtml(String originalString) {
		StringBuffer filteredString = new StringBuffer();
		ArrayList<Integer> charOffsets = new ArrayList<Integer>();
		for (int i = 0, k = 0; i < originalString.length(); i++) {
			String c = String.valueOf(originalString.charAt(i));
			if (originalString.charAt(i) == '<') {
				for (k = i + 1; k < originalString.length(); k++) {
					if (originalString.charAt(k) == '<') {
						k = i;
						break;
					}
					if (originalString.charAt(k) == '>') {
						break;
					}
				}
				i = k;
			} else {
				if (!isPunctuationChar(c)) {
					filteredString.append(c);
					charOffsets.add(i);
				}
			}
		}
		PunctuationOrHtmlFilteredResult result = new PunctuationOrHtmlFilteredResult();
		result.setOriginalString(originalString);
		result.setFilteredString(filteredString);
		result.setCharOffsets(charOffsets);
		return result;
	}

	private static FilteredResult filter(PunctuationOrHtmlFilteredResult pohResult, char replacement) {
		StringBuffer sentence = pohResult.getFilteredString();
		ArrayList<Integer> charOffsets = pohResult.getCharOffsets();
		StringBuffer resultString = new StringBuffer(pohResult.getOriginalString());
		StringBuffer badWords = new StringBuffer();
		int level = 0;
		setNodeFromRedis();  //JedisUtil.getObject("WORD_FILTER_NODE", RedisConstants.SYSTEM);
		Node node = tree;
		int start = 0, end = 0;
		for (int i = 0; i < sentence.length(); i++) {
			start = i;
			end = i;
			node = tree;
			for (int j = i; j < sentence.length(); j++) {
				node = node.findChar(sentence.charAt(j));
				if (node == null) {
					break;
				}
				if (node.isEnd()) {
					end = j;
					level = node.getLevel();
				}
			}
			if (end > start) {
				for (int k = start; k <= end; k++) {
					resultString.setCharAt(charOffsets.get(k), replacement);
				}
				if (badWords.length() > 0)
					badWords.append(",");
				badWords.append(sentence.substring(start, end + 1));
				i = end;
			}
		}
		FilteredResult result = new FilteredResult();
		result.setOriginalContent(pohResult.getOriginalString());
		result.setFilteredContent(resultString.toString());
		result.setBadWords(badWords.toString());
		result.setLevel(level);
		return result;
	}

	/**
	 * 简单句子过滤 不处理特殊符号，不处理html，简单句子的过滤 不能过滤中间带特殊符号的关键词，如：黄_色_漫_画
	 * 
	 * @param sentence 需要过滤的句子
	 * @param replacement 关键词替换的字符
	 * @return 过滤后的句子
	 */
	public static String simpleFilter(String sentence, String replacement) {
		StringBuffer sb = new StringBuffer();
//		tree =  JedisUtil.getObject("WORD_FILTER_NODE", RedisConstants.SYSTEM);
		setNodeFromRedis();
		Node node = tree;
		int start = 0, end = 0;
		for (int i = 0; i < sentence.length(); i++) {
			start = i;
			end = i;
			node = tree;
			for (int j = i; j < sentence.length(); j++) {
				node = node.findChar(sentence.charAt(j));
				if (node == null) {
					break;
				}
				if (node.isEnd()) {
					end = j;
				}
			}
			if (end > start) {
				for (int k = start; k <= end; k++) {
					sb.append(replacement);
				}
				i = end;
			} else {
				sb.append(sentence.charAt(i));
			}
		}
		return sb.toString();
	}

	/**
	 * 纯文本过滤，不处理html标签， 直接将去除所有特殊符号后的字符串拼接后进行过滤，可能会去除html标签内的文字，比如：如果有关键字“fuckfont”，过滤fuck<font>a</font>后的结果为****<****>a</font>
	 * 
	 * @param originalString 原始需过滤的串
	 * @param replacement 替换的符号
	 * @return
	 */
	public static FilteredResult filterText(String originalString, char replacement) {
		return filter(filterPunctation(originalString), replacement);
	}

	/**
	 * html过滤，处理html标签，不处理html标签内的文字，略有不足，会跳过<>标签内的所有内容，比如：如果有关键字“fuck”，过滤<a title="fuck">fuck</a>后的结果为<a title="fuck">****</a>
	 * 
	 * @param originalString 原始需过滤的串
	 * @param replacement 替换的符号
	 * @return
	 */
	public static FilteredResult filterHtml(String originalString, char replacement) {
		return filter(filterPunctationAndHtml(originalString), replacement);
	}

	/**
	 * 是否有脏词  （返回为空 表示没有脏字）
	 * @param str 字符串
	 * @return String 脏词 （返回脏词）
	 * @exception 
	 * @since  1.0.0
	 */
	public static String hasDirtyWord(String str) {
		String regex = "[\\pP\\pZ\\pS\\pM\\pC]";//符号 过滤
		String sentence = str.replaceAll(regex, "");
		String badWords = null;
//		tree =  JedisUtil.getObject("WORD_FILTER_NODE", RedisConstants.SYSTEM);
		setNodeFromRedis();
		Node node = tree;
		int start = 0, end = 0;
		for (int i = 0; i < sentence.length(); i++) {
			start = i;
			end = i;
			node = tree;
			for (int j = i; j < sentence.length(); j++) {
				node = node.findChar(sentence.charAt(j));
				if (node == null) {
					break;
				}
				if (node.isEnd()) {
					end = j;
				}
			}
			if (end > start) {
				badWords = sentence.substring(start, end + 1);
				break;
			}
		}
		return badWords;
	}
	
	private static class PunctuationOrHtmlFilteredResult {
		private String originalString;
		private StringBuffer filteredString;
		private ArrayList<Integer> charOffsets;

		public String getOriginalString() {
			return originalString;
		}

		public void setOriginalString(String originalString) {
			this.originalString = originalString;
		}

		public StringBuffer getFilteredString() {
			return filteredString;
		}

		public void setFilteredString(StringBuffer filteredString) {
			this.filteredString = filteredString;
		}

		public ArrayList<Integer> getCharOffsets() {
			return charOffsets;
		}

		public void setCharOffsets(ArrayList<Integer> charOffsets) {
			this.charOffsets = charOffsets;
		}
	}
	
	private static void setNodeFromRedis(){
		/*tree =  JedisUtil.getObject("WORD_FILTER_NODE", RedisConstants.SYSTEM);
		if(tree==null){
			glFilterVocabularyService.addGlFilterVocabulary();
			tree =  JedisUtil.getObject("WORD_FILTER_NODE", RedisConstants.SYSTEM);
		}*/
	}
	
	
}
